/////////////////////////////////////////////////////////////////////////////
// Original code from libhdfs3. Copyright (c) 2013 - 2014, Pivotal Inc.
// All rights reserved. Author: Zhanwei Wang
/////////////////////////////////////////////////////////////////////////////
//  Modifications by Kumo Inc.
// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <ktest/ktest.h>
#include <kmhdfs/server/located_block.h>
#include <kmhdfs/server/located_blocks.h>

using namespace Hdfs::Internal;

TEST(TestLocatedBlocks, TestFindBlock){
    // repro GPSQL-3051
    LocatedBlocksImpl *lbs = new LocatedBlocksImpl();

    // one element in blocks
    lbs->setFileLength(10*1024+500);
    LocatedBlock *blk = new LocatedBlock(10240);
    blk->setNumBytes(500);
    lbs->getBlocks().push_back(*blk);
    const LocatedBlock *lb = lbs->findBlock(10239);
    EXPECT_TRUE(lb == NULL);
    lb = lbs->findBlock(10240);
    EXPECT_TRUE(lb->getOffset() == blk->getOffset());
    EXPECT_TRUE(lb->getNumBytes() == blk->getNumBytes());

    lbs->getBlocks().clear();
    // 3 elements in blocks
    lbs->setFileLength(1024*2+100);
    LocatedBlock *blk1 = new LocatedBlock(0);
    blk1->setNumBytes(1024);
    LocatedBlock *blk2 = new LocatedBlock(1024);
    blk2->setNumBytes(1024);
    LocatedBlock *blk3 = new LocatedBlock(2048);
    blk3->setNumBytes(100);
    lbs->getBlocks().push_back(*blk1);
    lbs->getBlocks().push_back(*blk2);
    lbs->getBlocks().push_back(*blk3);

    lb = lbs->findBlock(-100);
    EXPECT_TRUE(lb == NULL);
    lb = lbs->findBlock(0);
    EXPECT_TRUE(lb->getOffset() == 0);
    lb = lbs->findBlock(100);
    EXPECT_TRUE(lb->getOffset() == 0);
    lb = lbs->findBlock(1023);
    EXPECT_TRUE(lb->getOffset() == 0);
    lb = lbs->findBlock(1024);
    EXPECT_TRUE(lb->getOffset() == 1024);
    lb = lbs->findBlock(1024+100);
    EXPECT_TRUE(lb->getOffset() == 1024);
    lb = lbs->findBlock(2047);
    EXPECT_TRUE(lb->getOffset() == 1024);
    lb = lbs->findBlock(2047);
    EXPECT_TRUE(lb->getOffset() == 1024);
    lb = lbs->findBlock(2048);
    EXPECT_TRUE(lb->getOffset() == 2048);
    lb = lbs->findBlock(2048+100-1);
    EXPECT_TRUE(lb->getOffset() == 2048);

    lb = lbs->findBlock(2048+100);
    EXPECT_TRUE(lb == NULL);
    lb = lbs->findBlock(2048+1000);
    EXPECT_TRUE(lb == NULL);

    delete blk;
    delete blk1;
    delete blk2;
    delete blk3;
    delete lbs;
}
